package com.fan.demo1;

import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.ShardingStrategyConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.core.rule.BindingTableRule;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.apache.shardingsphere.underlying.common.config.properties.ConfigurationPropertyKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

/**
 * @Description:
 * @Author: Fan
 * @Date: 2021/12/4 11:46
 * @Version 1.0
 **/
//@Configuration
//@ConditionalOnProperty(prefix = "spring.shardingsphere", name = "enabled", havingValue = "true", matchIfMissing = false)
//@EnableConfigurationProperties({ ShardingSphereConfigProperties.class })
@Slf4j
public class DataSourceConfiguration {

//    @Autowired
    ShardingSphereConfigProperties shardingSphereConfigProperties;

//    @Autowired
//    List<TableRuleConfiguration> tableRuleConfigurations;

//    @Bean
    DataSource shardingDataSource() throws SQLException {
        List<String> dataSourceNamesList = shardingSphereConfigProperties.getDataSourceNames();
        List<String> logicTableList = shardingSphereConfigProperties.getLogicTable();
        List<String> actualDataNodesList = shardingSphereConfigProperties.getActualDataNodes();
        List<String> shardingColumnsList = shardingSphereConfigProperties.getShardingColumns();
        List<String> shardingStrategysList = shardingSphereConfigProperties.getShardingStrategys();
//        List<String> bindingTableGroupsList = shardingSphereConfigProperties.getBindingTableGroups();

        // 数据源构建
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setDriverClassName(com.mysql.cj.jdbc.Driver.class.getName());
        hikariDataSource.setJdbcUrl(String.format("jdbc:mysql://%s:%s/%s?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8",
                shardingSphereConfigProperties.getHost(),
                shardingSphereConfigProperties.getPort(),
                shardingSphereConfigProperties.getDataSourceName()));
        hikariDataSource.setUsername(shardingSphereConfigProperties.getUsername());
        hikariDataSource.setPassword(shardingSphereConfigProperties.getPassword());

        if (logicTableList.size() <= 0 || actualDataNodesList.size() <= 0) {
            log.error("The logicTable and actualDataNodes should not be empty，logicTableList.size:{},actualDataNodeList.size:{}",
                    logicTableList.size(), actualDataNodesList.size());
        }

        // 表规则构建
        ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
//        List<String> bindingTableRuleList = new ArrayList<>();
        List<TableRuleConfiguration> tableRuleConfigurationList = new ArrayList<>();
        Map<String, DataSource> dataSourceMap = new HashMap<>();

        for (int i = 0; i < logicTableList.size(); i++) {
            TableRuleConfiguration tableRuleConfiguration = new TableRuleConfiguration(logicTableList.get(i),
                    actualDataNodesList.get(i));
            // 这里目前只做标准分片策略下的处理，其他分片策略可以之后进行扩展
            if (shardingStrategysList.get(i).equals(ShardingStrategy.STANDARD.name())) {
                ShardingStrategyConfiguration shardingStrategyConfiguration = new StandardShardingStrategyConfiguration(shardingColumnsList.get(i), new PreciseAndRangShardingAlgorithm(),
                        new PreciseAndRangShardingAlgorithm());
                tableRuleConfiguration.setTableShardingStrategyConfig(shardingStrategyConfiguration);
            }
//            bindingTableRuleList.add(bindingTableGroupsList.get(i));
            tableRuleConfigurationList.add(tableRuleConfiguration);
            dataSourceMap.put(dataSourceNamesList.get(i), hikariDataSource);
        }
//        shardingRuleConfiguration.getBindingTableGroups().addAll(bindingTableRuleList);
        shardingRuleConfiguration.getTableRuleConfigs().addAll(tableRuleConfigurationList);

        // 属性构建
        Properties properties = new Properties();
        properties.setProperty(ConfigurationPropertyKey.SQL_SHOW.getKey(),
                String.valueOf(shardingSphereConfigProperties.isSqlShow()));
        properties.setProperty(ConfigurationPropertyKey.SQL_SIMPLE.getKey(),
                String.valueOf(shardingSphereConfigProperties.isSqlSimple()));

        DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfiguration, properties);
        return dataSource;
    }
}
